package tij4.concurrent.source;

/*
    NotifyAll() 并不一定会唤醒处于wait()状态的线程
    当notifyAll()因某个特定锁而被调用时,只有等待这个锁的任务才会被唤醒
 */

import jdk.nashorn.internal.ir.Block;

import java.sql.Time;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class Blocker {
    synchronized void waitingCall() {
        try{
            while (!Thread.interrupted()) {
               wait();
                System.out.println(Thread.currentThread() + " ");
            }
        }catch (InterruptedException e) {
            //Ok to exit this way
        }
    }
    synchronized void prod() {
        notify();
    }
    synchronized void prodAll() {
        notifyAll();
    }
}

class Task implements Runnable {
    static Blocker blocker = new Blocker();
    public void run() {
        blocker.waitingCall();
    }
}

class Task2 implements Runnable {
    static Blocker blocker = new Blocker();

    @Override
    public void run() {
        blocker.waitingCall();
    }
}

public class NotifyVsNotifyAll {
    public static void main(String[] args) throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i <5 ; i++) {
            executorService.execute(new Task());
            executorService.execute(new Task2());
        }
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            boolean prod = true;
            @Override
            public void run() {
                if(prod) {
                    System.out.println("\nnotify()");
                    Task.blocker.prod();    //只会唤醒task,不是唤醒task2的
                    prod = false;
                }else {
                    System.out.println("\nnotifyAll()");
                    Task.blocker.prodAll();
                    prod = true;
                }
            }
        }, 400, 400);
        TimeUnit.SECONDS.sleep(5);
        timer.cancel();
        System.out.println("\nTimer canceled");
        TimeUnit.MILLISECONDS.sleep(500);
        System.out.println("\nShutting down");
        executorService.shutdownNow();
    }
}
